/*
   file : def_head.h
   全局性的变量、常量等
   University of Jiangsu
   memoryDB      2010.6
 */


#ifndef _MMDB_DEF_HEAD_HEAD_H
#define _MMDB_DEF_HEAD_HEAD_H

#include<dirent.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<time.h>
#include<sys/types.h>
#include<regex.h>
#include<pthread.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/tcp.h>
#include<errno.h>
#include<sys/stat.h>
#include<unistd.h>
#include<signal.h>

#define MAX_LINE 1024  
#define MAX_COMMAND 2048
#define MAX_NAME 50  	//数据库、表、属性的名称的最大长度
#define MAX_PWD 50 		//密码最大长度
#define NUM_OF_TB 20  	//一个数据库可设置的最大表的数目
#define NUM_OF_COLU 20 	//一个表可设置的最大属性数目
#define BLOCK_SIZE 4096  	//第四区域中块的大小
#define PORT 9989         	//默认端口

/*块头部结构*/
typedef struct{
	unsigned long pre; 		//相关联的前一块
	unsigned long next;		//相关联的下一块
	int tb;           	 	//块所属表
	int colu;			//如果是索引块,则要记录块所属属性id,-1表示是记录块
	unsigned long record_size;	//记录本块内存储的记录或索引的单条大小
	int unused; 			//记录块内还能存储多个条记录或索引
	int useable_offset; 		//块内可用的空闲记录
}BLOCK_HEAD;

/*块结构,包含一个头部和数据区*/
typedef struct{
	BLOCK_HEAD head;
	char data[BLOCK_SIZE-sizeof(BLOCK_HEAD)];
}BLOCK;

/*表示一条记录地址的结构*/
typedef struct{
	BLOCK *p_blk;  //块地址
	int off; 	 //data[off],即偏移量
}record_add;

/*属性结构*/
typedef struct{
	int id;  			//初为-1
	char colu_name[MAX_NAME];   //列属性名称，初为"\0"
	int length;  			//限长,初为-1
	int type;  			//0代表char *,1代表int,2代表float,初为-1
}COLU;

/*表结构*/
typedef struct{
	int id;  				//初始化为-1
	char tb_name[MAX_NAME];  		//数据表名称,初始化为"\0"
	int num_of_colu;  			//本表所含的列数目(属性数目),初始化为-1
//	unsigned long curr_colu;  		//指向第三区域中相应的当前可用的空闲属性,初为0
	unsigned long first_block;  	//指向本表第一个块的偏移量,初为0
	unsigned long useable_block;  	//指向第一个有空闲的可用块的偏移量,初为0
}TB;

/*数据库结构*/
typedef struct{
	char db_name[MAX_NAME];  	//数据库名称,初始化为"\0"
	unsigned long db_size;  	//创建数据库时指定的数据库大小,单位是bytes,初始化为0
	char pwd[MAX_PWD];  		//初始化为"\0"
}DB;



///////////////////////////////////////////////////////////////////////////
#define SIZE_DB sizeof(DB)  				//第一区域的大小
#define SIZE_TBS NUM_OF_TB*sizeof(TB)  			//第二区域的大小
#define SIZE_COLUS NUM_OF_TB*NUM_OF_COLU*sizeof(COLU)   //第三区域的大小


//////////////////////////////////////////////////////////////////////////////
/*
   共享内存中相关的全局指针,所有的对共享内存的操作都是通过对这些指针的操作来操作
 */
void *ptr;  //指向共享内存起始地址
DB *ptr_db;  //指向当前打开的数据库的DB结构
TB *ptr_tb;  //指向第一个表的TB结构
COLU *ptr_colu; //指向第一个COLU结构
BLOCK *ptr_blk; //指向数据区的首块
BLOCK *ptr_blk_curr; 

time_t system_start; //记录系统启动时间
time_t last_save_time;  //记录最后一次同步的时间
static const char SEP[]=",";  //每条记录中以','为分隔符
static char *db_dir="db_files/"; //数据文件存放目录。。!!!!!!注意!!!!!!! 目录名称需要以 "/" 结尾
int shmid; //记录共享内存的shmid
static unsigned long SIZE_ALL_ZONE=sizeof(DB) + NUM_OF_TB*sizeof(TB) + NUM_OF_TB*NUM_OF_COLU*sizeof(COLU);  //1、2、3区域的大小
static unsigned long MAX_BLOCK_NUM;  //系统中数据块的数目
int listenfd;  //服务端套接字


//一些正则表达式
static const char *reg_pwd="^\\w{1,50}$";  //密码,长度是1-50个字符,具体是不含空白的下划线、字母、数字
static const char *reg_name="^\\w{1,50}$";  //数据库、表、属性列的名称,具体规格同密码
//////////////////////////////////////////////////////////////////////////////

//计算执行时间
#define print_time(te,sockfd,START,END)\
	sprintf(te,"command costs %lu us\n",1000000*(END.tv_sec-START.tv_sec) + (END.tv_nsec-START.tv_nsec)/1000 );\
	if(sockfd!=1)strcat(te,"\n\n\n");\
	write(sockfd,te,strlen(te));\

//对不可重入函数 互斥锁
pthread_mutex_t fun_lock;
pthread_rwlock_t DB_lock;


typedef struct Table_lock
{
   char Table_Name[MAX_NAME];
   pthread_rwlock_t TB_lock;
   struct Table_lock *Next_lock;
}Table_lock;


typedef struct
{
    Table_lock *Table_lock_list;
    Table_lock *Last_lock;
}Table_lock_list;




////////////////////////////////////////////////////////////////////////////

enum Date_type{STRINGX,INTX,DOUBLEX};
enum Field_limit{NOT_NULLX,NOT_NULLX_UNIQUE,NOT_NULLX_PRIMARY_KEY};
enum Cmp_opt{EQU,THAN,LESS}; 
enum SQL_type{SELECTX,CREATEX,UPDATEX,INSERTX,DELETEX,DROPX};
enum Atom_type{VALUE,FIELD};
enum WhereType{ANDX,ORX};

typedef struct Field
{
	char Table_Name[MAX_NAME];
	char Field_Name[MAX_NAME];
	int Int_Val;
	double Double_Val;
	char Str_Val[MAX_LINE];
	int str_len;
    enum Date_type date_type;
    struct Field *Next_Field;
}Field;

typedef struct Table
{
	char Table_Name[MAX_NAME];
	Field *Field_list;
	Field *Last_Field;
	int Field_num; 
	struct Table *Next_Tab;
	
}Table;

typedef struct Record
{
	Field *Field_list;
    Field *Last_field;
	int Feild_num;
	struct Record *Next_record;
}Record;

typedef struct Row
{
	struct Row *next_row;
	record_add row_id;
}Row;

typedef struct
{
	enum Atom_type Atom_type;
	Field *Atom_field;
}Atom;

typedef struct Where_node
{
	char Table_name[MAX_NAME];
	Atom *R_atom;
	Atom *L_atom;
	enum Cmp_opt opt;
	struct Where_node *Next_where_node;
}Where_node;

typedef struct WhereTable
{
	char name[MAX_NAME];
	Where_node *Where_node_list;
	Where_node *last_node;
	struct WhereTable *Next_where_tab;
	int Where_node_num;

}WhereTable;

typedef struct
{
	enum WhereType where_type;
	WhereTable *Where_table_list;
}Where;

typedef struct
{
	 Table *Select_list;
	 Where *Select_where;

}Select;

typedef struct
{
	 Table *Tab;
}Create_Table;

typedef struct
{
	 Table *Tab;
	 Where *Select_where;
}Update;

typedef struct
{
	 Table *Tab;

}Insect;

typedef struct
{
    Where *Select_where;
    Table *Select_Table;
}Delete;

typedef struct
{
	char name[MAX_NAME];
}Drop_Table;

typedef struct
{
	Select *select_sentence;
	Create_Table *create_sentence;
	Update *update_sentence;
	Delete *delete_sentence;
	Insect *insect_sentence;
	Drop_Table *drop_sentence;
	Where *where_struct;
	Table *table_struct;
	Field *cur_table_field;
	enum Date_type Cur_date_type;
	char str[MAX_COMMAND];
	int sockfd;
	struct timespec time_st;
	struct timespec time_end;
}sql_sentence;

#endif
